home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
100 Great Games for Palm OS 1
/
100PalmV1.iso
/
Casino
/
pocket poker
/
ppoker10.csl
< prev
next >
Wrap
Text File
|
1998-07-19
|
52KB
|
2,149 lines
# ppoker10.csl, version 1.0
# Frank O'Brien
# Copyright (C) July 1998, Frank O'Brien,
# dianfrank@worldnet.att.net.
#
# Absolutely no warranty is given by author.
#
# The author has put a few hours into this program, as well as
# invested in the CASL development environment, and therefore would
# like to recover a small token in return from those users so moved.
# On the other hand, the author also wishes to contribute free of charge
# the source code to the CASL development community, for any help it may
# offer to new developers. This results in a rather unique hybrid
# shareware/freeware distribution policy.
#
# 1. The original PRC file may be distributed as $12 shareware.
# 2. The CSL source file and the CIC icon files may be distributed
# under the following conditions:
#
# a. The compiled PRC version of this original source code file is
# distributed by the original author as $12 shareware. There shall be
# no other commercial use of this source code file.
#
# b. Source code may be changed and distributed. Distributed changes
# shall be documented with name, type and date. Please also add a note
# to about box.
#
# c. You may distribute this source code file (with or without changes)
# to other owners of the CASL compiler for their use. The PRC file is
# not to be included, except as specified below.
#
# d. Distribution of the compiled PRC version of changes to this source
# code is allowed to a maximum of 20 people, and must be at no fee.
# This is intended to allow an author to distribute changes to a small
# group of friends, even if they do not own the CASL compiler. Posting
# to the Internet for unrestricted downloading is automatically assumed
# to violate the maximum 20 requirement, and therefore is not allowed.
# requires CASL runtime module 2.5x.
# when compiling this file, FOPP has been reserved as
# a unique creator ID. PocketPoker is intended (pilot)
# "desktop name". ppoker.cic is the intended icon file.
# fob 24Jun98
# first attempt at poker, deal 5 cards,
# recognize hand
# fob 29jun98
# worked on display and play state loop, finished ante and reconcile bet
# fob 30jun98
# completed play loop calling structure, all buttons and functions are
# there, but functions are skeleton
# fob 1jul98
# started filling in some of the play functions, do all except betting
# cycles
# fob 3jul98
# finished dealer selecting which cards to discard
# added bet form, filled in betting cycles, but dealer only passes or
# folds, no raises
# fob 4jul98
# added graphical card display
# use lbDWhat as shuffle, and other computing delay messages
# clear discard display while new cards coming
# show bet on main form after each bet
# make dealer bet functions more sophisticated
# add bluff to 2nd dealer bet round
# dress up bet form, fixed selector with multiple selections highlighted
# fob 5jul98
# fixed bug during 1st bet round dealer rank not correct, wrong hand
# added lots more comments
# tweaked DDealerBet1, DDealerBet2 desired hand ranks
# made bet input form relative to ante and houselimit
# added welcome screen
# version 0.1 released
# start of version 0.2
# fob 6jul98
# changed checkbox meaning to [x]=hold, [ ]=discard, due to user feedback
# added help screen with basic play and hand rank instructions
# start of version 0.3
# fob 8jul98
# minor fixes:
# dealer accepts bet. check keepers - clear this before doing 1st rank,
# 2nd round
# spell shuffling right
# in 2nd round, dealer is raising 200 with existing bet of 470. before
# that bet was 10+60 (user 1st round)+100 (user 2nd round)+200 (dealer
# 2nd round)+100 (user 2nd round).
# let dealer only bet in increments of ante.
# start of version 0.4
# fob 10jul98
# minor fixes
# in dealdraw, clear discarded cards first, then deal new cards, looks
# better, especially if shuffle happens
# show bet (ante) after hit deal button, don't wait until bet screen.
# add view off option for user draw recommendation
# fix bug where if have ace can hold any card and draw 4
# tried, doesn't work - maybe if use lines for cards, not rectangle,
# don't need redraw after frame show swap
# add help msg when check card ok button fails
# start of version 0.5
# fob 11jul98
# add option to change display units and houselimit
# start of version 0.6
# fob 19jul98
# add option to shuffle at each game start, or only when necessary
# added shareware/freeware licence and conditional compile
# released as version 1.0
# to do
# make dealer draw selector recognize almost straight, almost flush
# optimize hand ranker
# detect straights with low ace
# add sound
# add preferences, high score, and last score databases
# add dealer preferences database
# POKER STATE DIAGRAM
# key: []=tap to call invoker function, ()=program action leading to new state,
# R=dealer raise, B=bet round
# [btDeal] --> AnteUp --> Deal, clr R=0, clr B=0 -->
#
# UserBetPrep --> [btBet], [slBDigit0], [slBDigit1], [btBOK], if B=0 --> DDealerBet1
# UserBetPrep --> [btPass], if R=0 and B=0 --> DDealerBet1
# UserBetPrep --> [btPass], if R=1 and B=0 --> UserDrawSelectPrep
# UserBetPrep --> [btFold] --> ReconcileBet
#
# DDealerBet1 --> (Bet), set R=1 --> UserBetPrep
# DDealerBet1 --> (Pass) --> UserDrawSelectPrep
# DDealerBet1 --> (Fold) --> ReconcileBet
#
# UserDrawSelectPrep --> [ckHold], [btOK] --> DealerDrawSelect -->
# --> DealDraw, clr R=0, set B=1 -->
#
# UserBetPrep --> [btBet], [slBDigit0], [slBDigit1], [btBOK], if B=1 --> DDealerBet2
# UserBetPrep --> [btPass], if R=0 and B=1 --> DDealerBet2
# UserBetPrep --> [btPass], if R=1 and B=1 --> ReconcileBet
# UserBetPrep --> [btFold] --> ReconcileBet
#
# DDealerBet2 --> (Bet), set R=1 --> UserBetPrep
# DDealerBet2 --> (Pass) --> ReconcileBet
# DDealerBet2 --> (Fold) --> ReconcileBet
#
# ReconcileBet --> [btDeal]
# POKER RANK ALGORITHM
# basically a hexadecimal number is assigned to a poker hand, where the better
# hand is always the higher number. Technique seen in in article by Dick Pountain,
# Byte magazine, Jul91,
#
# the code:
#
# element no. d0 d1 d2 d3 d4 d5
# hand
#
# no hand 0 card5 card4 card3 card2 card1
# pair 1 pair odd3 odd2 odd1 0
# 2 pair 2 pair1 pair2 odd1 0 0
# 3 kind 3 three odd2 odd1 0 0
# straight 4 card5 0 0 0 0
# flush 5 card5 card4 card3 card2 card1
# full house 6 three two 0 0 0
# 4 kind 7 four odd1 0 0 0
# str-flush 8 card5 0 0 0 0
#
# where cardn, pairn, three, four, oddn is 2-14 value of card (2=2...j=11,q=12,k=13,a=14)
#
# rank = d0*16^5 + d1*16^4 + d2*16^3 + d3*16^2 + d4*16^1 + d5*16^0
#
# advantages: once ranked allows easy comparison of hands without alot of nested if/then's
# disadvantages: doesn't differentiate between same hands by suit, so considered tie
# (very rare)
# DEALER PERSONALITY
# the dealer's personality comes out during two betting rounds, and constants are provided
# to customize the dealer's decision making process.
# during each betting round, the dealer classifies its hand into "good", "ok", or "bad".
# based on minimum hand ranks. once the class is known, it has a maximum bet in mind.
# the minimum hand rank for each class, and maximum bet limit depends on which betting
# round it is in.
# during round 1 and round 2, if it has a good hand, and the max bet limit has not been
# exceeded, it will propose a raise. if it has an ok or bad hand and the max bet limit
# is not exceeded, it will stay. with an ok or bad hand, if the max bet limit is
# exceeded, it will fold.
# during round 2 if it chooses to bluff, it will propose a raise based on the good
# hand limit, irrespective of what hand rank it has.
# to adjust max bet limits, see nMaxGoodBet, nMaxOKBet, and nMaxBadBet. nMaxGoodBet is
# the house limit.
# to adjust min hand limits in round 1 for good hand, see nMinGoodRank1[],
# for ok hand, see nMinOKRank1[].
# to adjust min hand limits in round 2 for good hand, see nMinGoodRank2[],
# for ok hand, see nMinOKRank2[].
# see Poker Rank explanation for how to define array elements,
# to adjust bluffing rate, see nPercentBluff.
# max bet variables are initialized in DInitMaxBet, all other preference variables
# are initialized in variables section.
# for actual use of these constants see functions, DDealerBet1 and DDealerBet2.
#
# what's not customizable is withdraw card selection. this is done by poker ranker
# functions. any decisions are hard coded. the user is presented with the
# ranker's recommendations when the user must discard. the dealer always takes
# the ranker's recommendation.
# GLOBAL VARIABLES
variables;
bFreeware=true();
bRegistered=false();
end;
# GRAPHIC VARIABLES
variables;
nPx=1000/160; # 6.25 casl pixels = 1 real pilot pixel, 1000x1000 vs. 160x160
# this could be used for accessing 40 x 40 grid
nSp=4*nPx; # 25 = nice even increment for both pilot and casl
# this make the grid effectively 36 x 36
nT=4*nSp; # 100 = top margin so don't overwrite frame heading
nL=2*nSp; # 50 = left margin
# objects sized with these will fit on a 5 x 9 grid
nH=3*nSp; # 75 = height for objects, fits normal font
nSH=nSp; # 25 = vertical spacing between objects
nW=6*nSp; # 150 = width for objects, fits short words and cards
nSW=nSp; # 25 = hortizontal spacing between objects
# objects sized with this new width will fit on a 4 x 9 grid
nWW=8*nSp; # 200 = wide width for objects, fits longer words
# could use for fitting object onto a 7 x 9 grid, but not used this way
nNW=4*nSp; # 100 = narrow width for objects, fits very short words
end;
# CARD VARIABLES
variables;
# deck constants
numeric nShufs=10;
numeric nShufCards=10;
numeric nLastCard=52;
# deck variables
numeric nDeck[nLastCard];
numeric nNextCard; # index for deck array
end;
# POKER PLAYING VARIABLES
variables;
#numeric nTestHand[5]=0*13+9,1*13+9,2*13+9,3*13+9,2*13+8;
# user hand variables
numeric nHand[5];
numeric nRank[1]; # single element array used so can pass by reference
string sRank[1]; #
numeric bHold[5];
# dealer hand variables
numeric nDHand[5];
numeric nDRank[1];
string sDRank[1];
numeric bDHold[5];
# accounting constants
nAnte=1;
nBank=200;
# accounting variables, set by user preference
# all money is multiplied by units before display
numeric nUnits; # with units=10, bank=2000, for example
numeric nHouseLimit; # max. units each bet round
# accounting variables, measured in units
numeric nTempBet;
numeric nBet;
numeric nTotal;
# system flags, t/f
numeric bFold; # user folded
numeric bDFold; # dealer folded
numeric bRound2; # round 2 betting
numeric bDRaise; # dealer proposes raise
# system variables
numeric nForm; # 0=main,1=betinput,2=pref,3=help,4=about
numeric nPriorForm;
numeric nPriorPriorForm;
end;
# DEALER PERSONALITY VARIABLES
variables;
# max bets
numeric nMaxGoodBet; # must not exceed house limit
numeric nMaxOKBet;
numeric nMaxBadBet;
# min hands
nMinGoodRank1[6]=1,11,0,0,0,0; # pair of J's
nMinOKRank1[6]=0,14,0,0,0,0; # ace high
nMinGoodRank2[6]=2,7,2,0,0,0; # pair 7's and pair 2's
nMinOKRank2[6]=1,7,0,0,0,0; # pair 7's
# percent time will bluff by proposing raise on second round
nPercentBluff=20;
end;
# VARIABLES, BET INPUT FORM
variables;
sBetSelect[10]="0","1","2","3","4","5","6","7","8","9";
numeric nBExp0;
numeric nBExp1;
end;
# VARIABLES, MESSAGE FORM
variables;
string sMAbout1="PocketPoker 1.0"+
char(10)+char(10)+"Play five card draw poker against "+
"the PalmPilot."+
char(10)+char(10)+"Requires CASLrt 2.5x."+
char(10)+char(10)+"Uses poker hand ranking technique seen in "+
"article by Dick Pountain, Byte magazine, July 1991";
# 2nd variable needed to meet 255 char compile time limit
string sMAbout2=char(10)+char(10)+char(169)+
" July 1998, Frank O'Brien, "+
"dianfrank@worldnet.att.net.";
compile_if bFreeWare;
string sMAbout3=char(10)+char(10)+"Freeware when distributed "+
"as source code to CASL development community. For details, "+
"see PPokerDoc.htm. For updates, visit ";
string sMAbout4="http://home.att.net/~dianfrank/ppoker.htm.";
compile_else;
compile_if bRegistered;
string sMAbout3=char(10)+char(10)+"Registered "+
"version. Thank you. Updates will be automatically emailed. Please visit, ";
string sMAbout4="http://home.att.net/~dianfrank/pilot_apps.htm "+
"for other available programs.";
compile_else;
string sMAbout3=char(10)+char(10)+"$12 shareware. Unregistered "+
"version. If you like it, please visit, ";
string sMAbout4="http://home.att.net/~dianfrank/ppoker.htm "+
"for updates and payment methods.";
compile_end_if;
compile_end_if;
string sMHelp="Basic play: get 5 cards, bet, hold at least 2 cards "+
"(1 ace), you'll get new cards, bet again, highest hand wins"+
char(10)+char(10)+"Hand rank:"+char(10)+"Straight-Flush"+
char(10)+"4 of a kind"+char(10)+"Full house"+char(10)+
"Flush"+char(10)+"Straight"+char(10)+"3 of a kind"+char(10)+
"2 pair"+char(10)+"1 pair"+char(10)+"High card"+
char(10)+char(10)+"See PPokerDoc.htm for further details.";
end;
# VARIABLES, USER PREFERENCES
variables;
numeric bAllowPrefs;
numeric bRecommendHold; # show recommended hold cards
numeric bAtStart; # when to shuffle
string sUnits[6]="1","2","5","10","20","50";
string sHouseLimit[3]="10","20","50";
# default index for nUnits and nHouseLimit
numeric nUnitsI;
numeric nHouseLimitI;
end;
# OBJECTS
# OBJECTS, MAIN FORM
frame frMain;
display "PocketPoker";
end;
label lbCard[5], frMain;
font "largefont","",0;
pixel_size nW-2*nPx, nH+nSH;
display "";
end;
label lbDCard[5], frMain;
font "largefont","",0;
pixel_size nW-2*nPx, nH+nSH; # little fine tune for fitting inside card border
display "";
end;
button ckHold[5], frMain;
checkbox;
pixel_size nNW,nH;
display "";
end;
button btOK, frMain;
display "OK";
pixel_size nNW,nH;
end;
label lbWhat, frMain;
display "";
end;
label lbDWhat, frMain;
display "";
end;
button btDeal, frMain;
pixel_size nWW,75;
display "Deal";
position nL,nT+8*(nH+nSH);
hidden;
end;
button btBet, frMain;
pixel_size nWW,75;
display "Bet";
position nL+1*(nWW+nSW),nT+8*(nH+nSH);
hidden;
end;
button btPass, frMain;
pixel_size nWW,75;
display "Pass";
position nL+2*(nWW+nSW),nT+8*(nH+nSH);
hidden;
end;
button btFold, frMain;
pixel_size nWW,75;
display "Fold";
position nL+3*(nWW+nSW),nT+8*(nH+nSH);
hidden;
end;
label lbStatus, frMain;
display "";
end;
label lbTotal, frMain;
font "largefont","",0;
display "";
end;
# OBJECTS, MENU MAIN FORM
menu_top mtOptions, frMain;
display "Options";
end;
menu_item miPrefs, mtOptions;
display "Preferences...";
end;
menu_top mtHelp, frMain;
display "Help";
end;
menu_item miHelp, mtHelp;
display "Help...";
end;
menu_item miAbout, mtHelp;
display "About...";
end;
# OBJECTS, BET INPUT FORM
frame frBet;
display "Enter Bet";
hidden;
end;
label lbBRaise, frBet;
position nL,nT;
end;
label lbBTotal, frBet;
position nL+3*(nW+nSW),nT;
end;
label lbBHouseLimit, frBet;
position nL+3*(nW+nSW),nT+2*(nH+nSH);
end;
label lbBDigit0, frBet;
position nL,nT+1*(nH+nSH);
end;
label lbBDigit1, frBet;
position nL+1*(nW+nSW),nT+1*(nH+nSH);
end;
selector slBDigit0, frBet;
list sBetSelect;
pixel_size nW,6*(nH+nSH);
position nL,nT+2*(nH+nSH);
end;
selector slBDigit1, frBet;
list sBetSelect;
pixel_size nW,5*(nH+nSH);
position nL+1*(nW+nSW),nT+2*(nH+nSH);
end;
button btBOK, frBet;
display "OK";
pixel_size nWW,nH;
position nL+2*(nWW+nSW),nT+8*(nH+nSH);
end;
button btBReset, frBet;
display "Reset";
pixel_size nWW,nH;
position nL+1*(nWW+nSW),nT+8*(nH+nSH);
end;
# OBJECTS, MESSAGE FORM
frame frMsgBox;
hidden;
end;
text lbMMsgText, frMsgBox;
position nL,nT;
pixel_size 900,700;
no_input;
scrollbar top;
end;
button btMOK, frMsgBox;
position 400,900;
pixel_size nWW,nH;
display "OK";
end;
# OBJECTS, USER PREFERENCES
frame frPref;
display "Preferences";
hidden;
end;
button ckPRecommendHold, frPref;
position nL,nT+0*(nH+nSH);
pixel_size 7*(nW+nSW),nH;
checkbox;
display "Show discard recommendations";
end;
button ckPAtStart, frPref;
position nL,nT+1*(nH+nSH);
pixel_size 7*(nW+nSW),nH;
checkbox;
display "Shuffle at each game start";
end;
text lbPUnits, frPref;
position nL,nT+2*(nH+nSH);
pixel_size 2*(nW+nSW),2*(nH+nSH);
display "Select units for display";
no_input;
end;
text lbPHouseLimit, frPref;
position nL+3*(nW+nSW),nT+2*(nH+nSH);
pixel_size 2*(nW+nSW),2*(nH+nSH);
display "Select max bet in units";
no_input;
end;
selector slPUnits, frPref;
position nL+0*(nW+nSW),nT+4*(nH+nSH);
pixel_size nW,4*(nH+nSH)-nSH;
list sUnits;
end;
selector slPHouseLimit, frPref;
position nL+4*(nW+nSW),nT+4*(nH+nSH);
pixel_size nW,4*(nH+nSH)-nSH;
list sHouseLimit;
end;
text lbPWhat, frPref;
position nL+1.5*(nW+nSW),nT+4*(nH+nSH);
pixel_size 2*(nW+nSW),4*(nH+nSH)-nSH;
no_input;
end;
button btPOK, frPref;
position nL+2*(nWW+nSW),nT+8*(nH+nSH);
pixel_size nWW,nH;
display "OK";
end;
button btPReset, frPref;
position nL+1*(nWW+nSW),nT+8*(nH+nSH);
pixel_size nWW,nH;
display "Reset";
end;
# FUNCTIONS
# MISC MATH
#calculates base^exp, so don't need mathlib
#
function nfPower(numeric base, numeric exp) as numeric;
nfPower=1;
while exp>0;
nfPower=nfPower*base;
exp=exp-1;
end_while;
end;
#calculates the log10 integer portion of n, so don't need mathlib
#
function nfIntLog(numeric n) as numeric;
variables;
numeric e;
end;
e=0;
while n>=10;
n=int(n/10);
e=e+1;
end_while;
nfIntLog=e;
end;
# 5x9 GRID POSITIONS
# given 5 x 9 grid cell ref, col=0-4, row=0-8, returns x=0-999, y=0-999 in casl pixels
function nfXPos(numeric col) as numeric;
nfXPos=nL+col*(nW+nSW);
end;
function nfYPos(numeric row) as numeric;
nfYPos=nT+row*(nH+nSH);
end;
# GRAPHIC CARD FUNCTIONS
# given card ref, cardi=0-9, returns col=0-4, row=0-8
function nfColPos(numeric cardi) as numeric;
nfColPos=cardi%5;
end;
function nfRowPos(numeric cardi) as numeric;
if cardi>4;
nfRowPos=4;
else;
nfRowPos=1;
end_if;
end;
# given card string to display and cardi=0-4, draws box and display name,
# separate functions for user and dealer cards
function DrawCardUp(string name, numeric cardi);
# draw border
set frMain, pen, nfXPos(nfColPos(cardi)), nfYPos(nfRowPos(cardi));
draw frMain, rectangle, nW, 2*(nH+nSH)-nPx;
# display label
put lbCard[cardi], name;
show lbCard[cardi];
end;
function DrawDCardUp(string name, numeric cardi);
# draw border
set frMain, pen, nfXPos(nfColPos(cardi+5)), nfYPos(nfRowPos(cardi+5));
draw frMain, rectangle, nW, 2*(nH+nSH)-nPx;
# display label
put lbDCard[cardi], name;
show lbDCard[cardi];
end;
function DrawDCardDown(numeric cardi);
# display label
hide lbDCard[cardi];
# draw border
set frMain, pen, nfXPos(nfColPos(cardi+5)), nfYPos(nfRowPos(cardi+5));
fill frMain, rectangle, nW, 2*(nH+nSH)-nPx;
end;
function ClearCard(numeric cardi);
# draw border
set frMain, pen, nfXPos(nfColPos(cardi)), nfYPos(nfRowPos(cardi));
clear frMain, rectangle, nW, 2*(nH+nSH)-nPx;
# display label
hide lbCard[cardi];
end;
function ClearDCard(numeric cardi);
# draw border
set frMain, pen, nfXPos(nfColPos(cardi+5)), nfYPos(nfRowPos(cardi+5));
clear frMain, rectangle, nW, 2*(nH+nSH)-nPx;
# display label
hide lbDCard[cardi];
end;
# CARD FUNCTIONS
function InitDeck;
variables;
numeric i;
end;
# fill deck
i=0;
while i<52;
nDeck[i]=i;
i=i+1;
end_while;
nNextCard=52; # force shuffle
end;
#given cards to arrange, shufs times, randomly rearranges global deck array
# by exchanging card elements of array.
#
function Shuffle (numeric cards, numeric shufs);
variables;
numeric temp;
numeric i;
numeric j;
numeric n;
numeric m;
string s;
end;
get lbDWhat, s;
put lbDWhat, "Shuffling...";
i=0;
while i<shufs;
j=0;
while j<cards;
n=randomn(52);
m=randomn(52);
temp=nDeck[n];
nDeck[n]=nDeck[m];
nDeck[m]=temp;
j=j+1;
end_while;
i=i+1;
end_while;
put lbDWhat, s;
end;
# returns next card in deck 0-51, if last card, performs reshuffle first
#
function nfNextCard as numeric;
if nNextCard=nLastCard;
call Shuffle(nShufCards,nShufs);
nNextCard=0;
end_if;
nfNextCard=nDeck[nNextCard];
nNextCard=nNextCard+1;
end;
#given 0-51, returns 2-14
#
function nfFace(numeric n) as numeric;
nfFace=(n%13)+2;
end;
#given 0-51, returns 0-3
#
function nfSuit(numeric n) as numeric;
nfSuit=n%4;
end;
#given 0-51, returns display string for face 2-14
#
function sfFace(numeric n) as string;
n=nfFace(n);
if n > 1 and n < 10; # number 2-9
sfFace=Char(48+n);
end_if;
if n = 10; # 10
sfFace=Char(49)+Char(48);
end_if;
if n = 11; # jack
sfFace=Char(74);
end_if;
if n = 12; # queen
sfFace=Char(81);
end_if;
if n = 13; # king
sfFace=Char(75);
end_if;
if n = 14; # high ace
sfFace=Char(65);
end_if;
end;
#given 0-51, returns display string for 0-3 suit
#
function sfSuit(numeric n) as string;
n=nfSuit(n);
# do suit string for each platform, windows font doesn't have
# suit char
if platform = "windows";
if n=0;
sfSuit="d";
end_if;
if n=1;
sfSuit="c";
end_if;
if n=2;
sfSuit="h";
end_if;
if n=3;
sfSuit="s";
end_if;
else;
# pilot platform
sfSuit=Char(141+n);
end_if;
end;
function sfCardName(numeric n) as string;
sfCardName=sfFace(n)+sfSuit(n);
end;
# MISC ACCOUNTING FUNCTIONS
# takes any accounting variable, and multiplies by
# units for display purposes. what is label.
#
function sfMoney(string what,numeric n) as string;
sfMoney=what+string(n*nUnits,"#");
end;
# MISC MAIN FORM INITIALIZERS
# init data
#
function InitVariables;
nForm=0;
call InitDeck;
nTotal=nBank;
end;
# move objects into position
#
function ArrangeVisObjects;
variables;
numeric i;
end;
i=0;
while i<5;
move lbCard[i],nfXPos(nfColPos(i))+nPx,nfYPos(nfRowPos(i))+nPx;
move ckHold[i],nfXPos(nfColPos(i)),nfYPos(0);
move lbDCard[i],nfXPos(nfColPos(i+5))+nPx,nfYPos(nfRowPos(i+5))+nPx;
hide ckHold[i];
i=i+1;
end_while;
move btOK, nfXPos(4.5),nfYPos(0);
hide btOK;
move lbWhat, nfXPos(0),nfYPos(3);
move lbDWhat, nfXPos(0),nfYPos(6);
move lbStatus, nfXPos(0),nfYPos(7);
move lbTotal, nfXPos(3),nfYPos(7);
show frMain; #force redraw
end;
function Welcome;
variables;
sf[5]=3*13+12,0*13+11,1*13+10,2*13+9,3*13+8;
i=0;
end;
while i<5;
nHand[i]=sf[i];
call DrawCardUp(sfCardName(sf[i]),i);
i=i+1;
end_while;
put lbDWhat, "Let's play 5 card draw";
# display bank
put lbTotal, sfMoney("Total: ",nTotal);
end;
function ClearDisplay;
variables;
numeric i;
end;
# clear display
i=0;
while i<5;
ClearCard(i);
ClearDCard(i);
i=i+1;
end_while;
put lbWhat, "";
put lbDWhat, "";
put lbStatus, "";
# clear system redraw list
# causes crash on both winrt and pilotrt, if do before first set/draw command
clear frMain, rectangle, 0, 0;
end;
# after main form reshow, need to reput labels so show over redrawn graphics,
# only works on pilot
#
function RedrawHand;
variables;
numeric i;
end;
i=0;
while i<5;
#DrawCardUp(sfCardName(nHand[i]),i); # doesn't help on winrt
put lbCard[i], sfCardName(nHand[i]);
i=i+1;
end_while;
end;
# MISC RANK
#decode nRank, use for test display, when not sure sRank is right
#
function sDecodeRank(numeric n) as string;
variables;
numeric m;
numeric i;
string s;
end;
i=5;
s="";
while i>-1;
m=int(n/nfPower(16,i));
s=s+" "+string(m,"#");
n=n-(m*nfPower(16,i));
i=i-1;
end_while;
sDecodeRank=s;
end;
# RANK POKER HAND
# before rank detectors are used, hands are always first sorted
# to ease search for matches,
#
# given bysuit=0 sorts by face, =1 sorts by suit,
# sorts hand[] array so highest is first element,
# next highest is second, etc
# face order: high ace, king, ... two
# suit order: spade, heart, club, diamond
#
function SortHand(numeric hand[], numeric bysuit);
# scan all 5 cards, keep track of highest card, put
# in first slot
# scan last 4 cards, keep track of highest card,
# put in 2nd slot
# scan last 3 cards, keep track of highest card,...
variables;
numeric maxi; # slot with highest card
numeric temp; # temp card
numeric i;
numeric j;
end;
i=0;
while i<4; # don't need to do last card
maxi=i;
j=i+1;
while j<5;
if bysuit;
if nfSuit(hand[j])>nfSuit(hand[maxi]);
maxi=j;
end_if;
else;
if nfFace(hand[j])>nfFace(hand[maxi]);
maxi=j;
end_if;
end_if;
j=j+1;
end_while;
temp=hand[i];
hand[i]=hand[maxi];
hand[maxi]=temp;
i=i+1;
end_while;
end;
# next 3 functions are low level comparators for
# determining hand rank
#
# given hand array and i element, looks at next neighboring i+1 card
# for match, returns true, or false
# use for like kinds
#
function bfEqualFace(numeric hand[],numeric i) as numeric;
bfEqualFace=nfFace(hand[i])=nfFace(hand[i+1]);
end;
# use for flushes
#
function bfEqualSuit(numeric hand[],numeric i) as numeric;
bfEqualSuit=nfSuit(hand[i])=nfSuit(hand[i+1]);
end;
# use for straights
#
function bfNextFace(numeric hand[],numeric i) as numeric;
bfNextFace=nfFace(hand[i])=nfFace(hand[i+1])+1;
end;
# next functions are detectors for each type of hand, return t/f
# side effects, if returns true:
# hand is resorted by face,
# nrank and srank are assigned the rank value
# bhold is assigned t/f discard recommendations
# nrank, srank, bhold are always completely reassigned, there is never
# remnant information remaining (no intialization needed)
# side effects, if returns false:
# hand may be resorted by face or suit,
# contents of all other inputs not specified
# use for detecting flush, d0=5
#
function bfFlush(numeric hand[], numeric nrank[], string srank[], numeric bhold[]) as numeric;
variables;
numeric f;
numeric i;
end;
SortHand(hand,1);
f=false();
if bfEqualSuit(hand,0);
# pair detected
if bfEqualSuit(hand,1);
# triple detected
if bfEqualSuit(hand,2);
# quad detected
if bfEqualSuit(hand,3);
# quin detected
f=true();
nrank[0]=5*nfPower(16,5);
srank[0]="Flush";
SortHand(hand,0);
i=0;
while i<5;
nrank[0]=nrank[0]+nfFace(hand[i])*nfPower(16,4-i);
srank[0]=srank[0]+", "+sfFace(hand[i]);
bhold[i]=true();
i=i+1;
end_while;
srank[0]=srank[0]+" high";
end_if;
end_if;
end_if;
end_if;
bfFlush=f;
end;
# use for detecting staight, d0=4
#
function bfStraight(numeric hand[], numeric nrank[], string srank[], numeric bhold[]) as numeric;
variables;
numeric f;
numeric i;
end;
SortHand(hand,0);
f=false();
if bfNextFace(hand,0);
# pair detected
if bfNextFace(hand,1);
# triple detected
if bfNextFace(hand,2);
# quad detected
if bfNextFace(hand,3);
# quin detected
f=true();
nrank[0]=4*nfPower(16,5)+nfFace(hand[0])*nfPower(16,4);
srank[0]="Straight, "+sfFace(hand[0])+" high";
i=0;
while i<5;
bhold[i]=true();
i=i+1;
end_while;
end_if;
end_if;
end_if;
end_if;
bfStraight=f;
end;
# detects straight flush, d0=8
#
function bfStraightFlush(numeric hand[], numeric nrank[], string srank[], numeric bhold[]) as numeric;
variables;
numeric f;
numeric i;
end;
f=0;
if bfFlush(hand, nrank, srank, bhold) and bfStraight(hand, nrank, srank, bhold);
f=true();
nrank[0]=8*nfPower(16,5)+nfFace(hand[0])*nfPower(16,4);
srank[0]="Straight Flush, "+sfFace(hand[0])+" high";
i=0;
while i<5;
bhold[i]=true();
i=i+1;
end_while;
end_if;
bfStraightFlush=f;
end;
# four of a kind, d0=7
#
function bfFourKind(numeric hand[], numeric nrank[], string srank[], numeric bhold[]) as numeric;
variables;
numeric f;
numeric i;
numeric j;
end;
SortHand(hand,0);
f=false();
i=0;
while i<2; # no point checking last 3 cards
if bfEqualFace(hand,i);
# pair detected
if bfEqualFace(hand,i+1);
# triple detected
if bfEqualFace(hand,i+2);
# quad detected
f=true();
nrank[0]=7*nfPower(16,5)+nfFace(hand[i])*nfPower(16,4);
srank[0]="Four "+sfFace(hand[i])+"'s";
j=0;
while j<5;
if j=i or j=i+1 or j=i+2 or j=i+3;
bhold[i]=true();
else;
nrank[0]=nrank[0]+nfFace(hand[j])*nfPower(16,3);
srank[0]=srank[0]+", "+sfFace(hand[j]);
if nfFace(hand[j])>=11;
bhold[i]=true();
else;
bhold[i]=false();
end_if;
end_if;
j=j+1;
end_while;
srank[0]=srank[0]+" high";
i=5; #force loop exit
end_if;
end_if;
end_if;
i=i+1;
end_while;
bfFourKind=f;
end;
# full house, d0=6
#
function bfFullHouse(numeric hand[], numeric nrank[], string srank[], numeric bhold[]) as numeric;
variables;
numeric f;
numeric i;
numeric j;
numeric k;
end;
SortHand(hand,0);
f=false();
i=0;
# check for triple
while i<3; # no point checking last 2 cards
if bfEqualFace(hand,i);
# pair detected
if bfEqualFace(hand,i+1);
# triple starts at i, check for 2nd pair
j=0;
while j<4;
if j=i or j=i+1 or j=i+2 or j=i-1; # i-1 prevents false detect when 4kind
else;
# check for 2nd pair
if bfEqualFace(hand,j);
# detected 2 pair at j, 1st triple starts at i,
f=true();
nrank[0]=6*nfPower(16,5)+nfFace(hand[i])*nfPower(16,4)+nfFace(hand[j])*nfPower(16,3);
srank[0]="Full House, "+sfFace(hand[i])+"'s over "+sfFace(hand[j])+"'s";
k=0;
while k<5;
bhold[k]=true();
k=k+1;
end_while;
# no odd card
j=5; # force exit
i=5; #
end_if;
end_if;
j=j+1;
end_while;
end_if;
end_if;
i=i+1;
end_while;
bfFullHouse=f;
end;
# three of a kind, d0=3
#
function bfThreeKind(numeric hand[], numeric nrank[], string srank[], numeric bhold[]) as numeric;
variables;
numeric f;
numeric i;
numeric j;
numeric n;
end;
SortHand(hand,0);
f=false();
i=0;
while i<3; # no point checking last 2 cards
if bfEqualFace(hand,i);
# pair detected
if bfEqualFace(hand,i+1);
# triple detected
f=true();
nrank[0]=3*nfPower(16,5)+nfFace(hand[i])*nfPower(16,4);
srank[0]="Three "+sfFace(hand[i])+"'s";
j=0;
n=3;
while j<5;
if j=i or j=i+1 or j=i+2;
bhold[j]=true();
else;
nrank[0]=nrank[0]+nfFace(hand[j])*nfPower(16,n);
srank[0]=srank[0]+", "+sfFace(hand[j]);
bhold[j]=false();
n=n-1;
end_if;
j=j+1;
end_while;
srank[0]=srank[0]+" high";
i=5; #force loop exit
end_if;
end_if;
i=i+1;
end_while;
bfThreeKind=f;
end;
# two pair, d0=2
#
function bfTwoPair(numeric hand[], numeric nrank[], string srank[], numeric bhold[]) as numeric;
variables;
numeric f;
numeric i;
numeric j;
numeric n;
end;
SortHand(hand,0);
f=false();
i=0;
while i<4; # no point checking last card
if bfEqualFace(hand,i);
# pair detected
j=0;
while j<4;
if j=i or j=i+1 or j=i-1; # i-1 prevents false detect when 3kind
else;
# check for another pair
if bfEqualFace(hand,j);
# detected 2 pair, 1st pair starts at i,
# 2nd pair starts at j
f=true();
nrank[0]=2*nfPower(16,5)+nfFace(hand[i])*nfPower(16,4)+nfFace(hand[j])*nfPower(16,3);
srank[0]="Two Pair, "+sfFace(hand[i])+"'s and "+sfFace(hand[j])+"'s";
# find odd card
n=0;
while n<5;
if n=i or n=i+1 or n=j or n=j+1;
bhold[n]=true();
else;
nrank[0]=nrank[0]+nfFace(hand[n])*nfPower(16,2);
srank[0]=srank[0]+", "+sfFace(hand[n])+" high";
bhold[n]=false();
end_if;
n=n+1;
end_while;
j=5; # force exit
i=5; #
end_if;
end_if;
j=j+1;
end_while;
end_if;
i=i+1;
end_while;
bfTwoPair=f;
end;
# one pair, d0=1
#
function bfOnePair(numeric hand[], numeric nrank[], string srank[], numeric bhold[]) as numeric;
variables;
numeric f;
numeric i;
numeric j;
numeric n;
end;
SortHand(hand,0);
f=false();
i=0;
while i<4; # no point checking last card
if bfEqualFace(hand,i);
# pair detected
f=true();
nrank[0]=1*nfPower(16,5)+nfFace(hand[i])*nfPower(16,4);
srank[0]="Two "+sfFace(hand[i])+"'s";
j=0;
n=3;
while j<5;
if j=i or j=i+1;
bhold[j]=true();
else;
nrank[0]=nrank[0]+nfFace(hand[j])*nfPower(16,n);
srank[0]=srank[0]+", "+sfFace(hand[j]);
n=n-1;
bhold[j]=false();
end_if;
j=j+1;
end_while;
srank[0]=srank[0]+" high";
i=5; #force loop exit
end_if;
i=i+1;
end_while;
bfOnePair=f;
end;
# high card, d0=0
#
function NoHand(numeric hand[], numeric nrank[], string srank[], numeric bhold[]);
variables;
numeric i;
end;
SortHand(hand,0);
nrank[0]=0;
srank[0]="High Card";
i=0;
while i<5;
nrank[0]=nrank[0]+nfFace(hand[i])*nfPower(16,4-i);
srank[0]=srank[0]+", "+sfFace(hand[i]);
i=i+1;
end_while;
# keep high card
bhold[0]=true();
if hand[0]=14;
# can discard 4 or 3 cards
if hand[1]>=11;
# keep jack or better too
bhold[1]=true();
else;
# discard 4 cards
bhold[1]=false();
end_if;
else;
# can only discard 3 cards
bhold[1]=true();
end_if;
# discard last 3 cards
bhold[2]=false();
bhold[3]=false();
bhold[4]=false();
end;
# Rank is main calling function
#first go, not very efficient, for example the hand must be looked at about
# thousand times before determining what rank hand is. fully tested and is
# accurate, so will use for now.
#sfRank benchmarking data for comparision later when trying to optimize:
# pair 3070 ms
# " 3080
# 2 pair 2670
# " 2670
# hcard, 3230 high card takes longest since is longest logic path
# 2 pair 2610
# hcard 3380
# pair 3050
# " 3100
# " 3130
# triple 2390
# the main ranker, call with user or dealer arrays, (by reference so
# assigned values persist after call)
# side effects:
# hand is sorted by face,
# nrank and srank are assigned the rank value
# bhold is assigned t/f keep recommendations
# nrank, srank, bhold are always completely reassigned, there is never
# remnant information remaining (no intialization needed)
# while processing displays wait message to lbDWhat
#
function Rank(numeric hand[], numeric nrank[], string srank[], numeric bhold[]);
variables;
string s;
end;
get lbDWhat, s;
put lbDWhat, "Ranking hand..."; # feedback for user, so knows pilot busy
if bfStraightFlush(hand, nrank, srank, bhold);
else;
if bfFourKind(hand, nrank, srank, bhold);
else;
if bfFullHouse(hand, nrank, srank, bhold);
else;
if bfFlush(hand, nrank, srank, bhold);
else;
if bfStraight(hand, nrank, srank, bhold);
else;
if bfThreeKind(hand, nrank, srank, bhold);
else;
if bfTwoPair(hand, nrank, srank, bhold);
else;
if bfOnePair(hand, nrank, srank, bhold);
else;
call NoHand(hand, nrank, srank, bhold);
end_if;
end_if;
end_if;
end_if;
end_if;
end_if;
end_if;
end_if;
put lbDWhat, s;
end;
# MISC POKER HAND RECOGNIZERS
function bfHoldAce(numeric hand[],numeric bhold[]) as numeric;
variables;
numeric i;
numeric f;
end;
f=0;
i=0;
while i<5;
if nfFace(hand[i])=14 and bhold[i];
f=true();
i=5;
end_if;
i=i+1;
end_while;
bfHoldAce=f;
end;
# PLAY POKER
# user and dealer ante up
#
function AnteUp;
# clear display
call ClearDisplay;
# ante up
nBet=nAnte;
put lbStatus, sfMoney("Bet: ",nBet);
# clear fold flags
bFold=false();
bDFold=false();
end;
# given prompt for user, makes user bet state active
# global flags for bet round, and dealer raise
#
function UserBetPrep(string s);
put lbDWhat, s;
put lbTotal, sfMoney("Total: ",nTotal);
put lbStatus, sfMoney("Bet: ",nBet);
if bDRaise;
put btPass, "See";
else;
put btPass, "Pass";
end_if;
show btBet;
show btPass;
show btFold;
end;
# deal user and dealer hands
#
function Deal;
variables;
numeric i;
end;
if bAtStart;
nNextCard=nLastCard;
end_if;
# fill hand arrays, and display user hand, back of dealer hand
i=0;
while i<5;
nHand[i]=nfNextCard;
DrawCardUp(sfCardName(nHand[i]), i);
#nHand[i]=nTestHand[i]; # put in for forcing hand
nDHand[i]=nfNextCard;
DrawDCardDown(i); #put lbDCard[i], sfCardBack();
i=i+1;
end_while;
# determine user rank, time consuming on pilot, approx 3s
#i=timevalue(); # @put in for benchmarking
call Rank(nHand, nRank, sRank, bHold);
#i=timevalue()-i; # @
# display sorted user hand
i=0;
while i<5;
ClearCard(i);
DrawCardUp(sfCardName(nHand[i]), i);
i=i+1;
end_while;
# display rank
put lbWhat, sRank[0]; # @comment out
#put lbWhat, sRank[0]+string(i,"######.#"); # @
# determine dealer rank, needed before DDealerBet1
put lbDWhat, "";
Rank(nDHand,nDRank,sDRank, bDHold);
# get ready for user bet round1
bRound2=false();
bDRaise=false();
nTempBet=0;
call UserBetPrep("Make your bet");
end;
# game over, determine winner
#
function ReconcileBet;
variables;
numeric i;
end;
put lbDWhat, "";
# determine winner
if bFold;
# user folded
nTotal=nTotal-nBet;
put lbStatus, sfMoney("Fold, you lose ",nBet);
else;
if bDFold;
# dealer folded
nTotal=nTotal+nBet;
put lbStatus, sfMoney("Fold, you win ",nBet)+"!";
else;
# display dealer hand
i=0;
while i<5;
ClearDCard(i);
DrawDCardUp(sfCardName(nDHand[i]),i);
i=i+1;
end_while;
# display dealer rank
put lbDWhat, sDRank[0];
# duke it out
if nRank[0]=nDRank[0];
put lbStatus, "Tie, can't rank suit";
else;
if nRank[0]>nDRank[0];
nTotal=nTotal+nBet;
put lbStatus, sfMoney("You win ",nBet)+"!";
else;
nTotal=nTotal-nBet;
put lbStatus, sfMoney("Sorry, you lose ",nBet);
end_if;
end_if;
end_if;
end_if;
# display bank
put lbTotal, sfMoney("Total: ",nTotal);
# user starts deal when ready
bAllowPrefs=true();
show btDeal;
end;
function UserDrawSelectPrep;
variables;
numeric i;
end;
# prepare for user draw select
i=0;
while i<5;
if not bRecommendHold;
bHold[i]=false();
end_if;
put ckHold[i], bHold[i];
show ckHold[i];
i=i+1;
end_while;
put lbDWhat, "Dealer accepts bet. Check to hold";
put lbTotal, sfMoney("Total: ",nTotal);
put lbStatus, sfMoney("Bet: ",nBet);
show btOK;
end;
# deal cards to replace discards to both user and dealer
#
function DealDraw;
variables;
numeric i;
numeric n;
end;
# clear card, then deal card if user check flag set
i=0;
while i<5;
if not bHold[i];
ClearCard(i);
end_if;
i=i+1;
end_while;
i=0;
while i<5;
if not bHold[i];
nHand[i]=nfNextCard;
DrawCardUp(sfCardName(nHand[i]),i);
end_if;
i=i+1;
end_while;
# determine user rank
put lbDWhat, "";
call Rank(nHand, nRank, sRank, bHold);
# display sorted user hand
i=0;
while i<5;
ClearCard(i);
DrawCardUp(sfCardName(nHand[i]),i);
i=i+1;
end_while;
# display user rank
put lbWhat, sRank[0];
# deal card if dealer flag set, count how many
n=0;
i=0;
while i<5;
if not bDHold[i];
# if show, can give away pair to user, etc
nDHand[i]=nfNextCard;
n=n+1;
end_if;
i=i+1;
end_while;
# determine dealer rank, needed before DDealerBet2
put lbDWhat, "";
Rank(nDHand,nDRank,sDRank, bDHold);
# set round 2 bet flag
bRound2=true();
bDRaise=false();
nTempBet=0;
call UserBetPrep("Dealer drew "+string(n,"#")+" cards. Make your bet");
end;
# DEALER PERSONALITY FUNCTIONS
function DInitMaxBets(numeric max);
# max bets
nMaxGoodBet=max; # must not exceed house limit
nMaxOKBet=int(nMaxGoodBet/2);
nMaxBadBet=int(nMaxOKBet/2);
end;
# given hand rank array, computes rank number
#
function nfDMakeRank(numeric rank[]) as numeric;
variables;
numeric i;
end;
nfDMakeRank=0;
i=0;
while i<6;
nfDMakeRank=nfDMakeRank+rank[5-i]*nfPower(16,i);
i=i+1;
end_while;
end;
function DDealerBet1;
variables;
numeric maxbet;
numeric braise;
end;
# dealer determines action based on its hand and user bet
braise=false();
if nDRank[0]>=nfDMakeRank(nMinGoodRank1);
# 1st round good hand
braise=true();
maxbet=int(nMaxGoodBet);
else;
if nDRank[0]>=nfDMakeRank(nMinOKRank1);
# 1st round ok hand
maxbet=nMaxOKBet;
else;
# 1st round bad hand
maxbet=nMaxBadBet;
end_if;
end_if;
if braise;
# accept bet and...
nBet=nBet+nTempBet;
if nBet<maxbet;
# suggest raise
bDRaise=true();
# round to nearest aAnte
nTempBet=int((maxbet-nBet)/2/nAnte)*nAnte;
call UserBetPrep(sfMoney("Dealer accepts and raises ",
nTempBet));
else;
# prepare for user draw select
call UserDrawSelectPrep;
end_if;
else;
if nBet+nTempBet<=maxbet;
# accept bet
nBet=nBet+nTempBet;
call UserDrawSelectPrep;
else;
# fold
bDFold=true();
call ReconcileBet;
end_if;
end_if;
end;
function DDealerBet2;
variables;
numeric maxbet;
numeric braise;
end;
# dealer determines action based on its hand and user bet
braise=false();
if nDRank[0]>=nfDMakeRank(nMinGoodRank2) or nPercentBluff>randomn(100);
# 2nd round good hand or bluff
braise=true();
maxbet=2*nMaxGoodBet;
else;
if nDRank[0]>=nfDMakeRank(nMinOKRank2);
# 2nd round ok hand
maxbet=2*nMaxOKBet;
else;
# 2nd round bad hand
maxbet=2*nMaxBadBet;
end_if;
end_if;
if braise;
# accept bet and...
nBet=nBet+nTempBet;
if nBet<maxbet;
# suggest raise
bDRaise=true();
nTempBet=int((maxbet-nBet)/2/nAnte)*nAnte;
call UserBetPrep(sfMoney("Dealer accepts and raises ",
nTempBet));
else;
put lbDWhat, "Dealer accepts bet";
put lbTotal, sfMoney("Total: ",nTotal);
put lbStatus, sfMoney("Bet: ",nBet);
call ReconcileBet;
end_if;
else;
if nBet+nTempBet<=maxbet;
# accept bet
nBet=nBet+nTempBet;
put lbDWhat, "Dealer accepts bet";
put lbTotal, sfMoney("Total: ",nTotal);
put lbStatus, sfMoney("Bet: ",nBet);
call ReconcileBet;
else;
# fold
bDFold=true();
call ReconcileBet;
end_if;
end_if;
end;
# determine what cards dealer would like to discard
#
function DealerDrawSelect;
# draw cards already known from rank during Deal function
call DealDraw;
end;
# FUNCTIONS, BET INPUT FORM
function BDisplayBetLabels();
# display bet selectors labels with their increment * nUnits
put lbBDigit0, sfMoney("",nfPower(10,nBExp0))+"'s";
put lbBDigit1, sfMoney("",nfPower(10,nBExp1))+"'s";
end;
function BDisplayHouseLimit(numeric br2);
variables;
numeric i;
end;
i=nHouseLimit;
if br2;
i=2*i;
end_if;
put lbBHouseLimit, sfMoney("Max Bet: ",i);
end;
# given br2=t/f for bet round2, sets up bet input form
#
function BInitBet(numeric br2);
# determine best bet increment, based on nHouseLimit
# power of 10 magnitude, nHouseLimit must be >= 10
# or decimal increment won't display
nBExp1=nfIntLog(nHouseLimit);
nBExp0=nBExp1-1;
# set max range based on nHouseLimit
if nfPower(10,nBExp1)>nHouseLimit;
# don't need
put slBDigit1,-1;
else;
if 9*nfPower(10,nBExp1)>nHouseLimit;
# clip range
put slBDigit1,-int((nHouseLimit)/nfPower(10,nfIntLog(nHouseLimit))+0.5);
else;
# max range ok
put slBDigit1,-10;
end_if;
end_if;
if nfPower(10,nBExp0)>nHouseLimit;
# don't need
put slBDigit0,-1;
else;
if 9*nfPower(10,nBExp0)>nHouseLimit;
# clip range
put slBDigit0,-int((nHouseLimit)/nfPower(10,nfIntLog(nHouseLimit))+0.5);
else;
# max range ok
put slBDigit0,-10;
end_if;
end_if;
call BDisplayBetLabels;
call BDisplayHouseLimit(br2);
end;
function BDisplayBet;
variables;
numeric d1;
numeric d2;
end;
get slBDigit0, d1;
get slBDigit1, d2;
nTempBet=d2*nfPower(10,nBExp1)+d1*nfPower(10,nBExp0);
put lbBRaise, sfMoney("New bet: ",nTempBet);
put lbBTotal, sfMoney("Total bet: ",nTempBet+nBet);
end;
function BClearBet(numeric br2);
# clear suggested bet
nTempBet=0;
# reset selectors to 0 default
put slBDigit0,0;
put slBDigit1,0;
# display bet
call BDisplayBet;
call BDisplayHouseLimit(br2);
# gets rid of double ghost highlighting
hide slBDigit0;
hide slBDigit1;
show slBDigit0;
show slBDigit1;
end;
# FUNCTIONS, PREFERENCES FORM
function PDisplayUnits;
put slPUnits,nUnitsI;
nUnits=value(sUnits[nUnitsI]);
end;
function PDisplayHouseLimit;
put slPHouseLimit,nHouseLimitI;
nHouseLimit=value(sHouseLimit[nHouseLimitI]);
end;
function PDisplayPrefStatus;
put lbPWhat,sfMoney("Ante=",nAnte)+", "+sfMoney("Total=",nTotal)+
", "+sfMoney("Max Bet=",nHouseLimit);
end;
function PDefaultPrefs;
# default show hold recommendations
bRecommendHold=true();
bAtStart=true();
put ckPRecommendHold, bRecommendHold;
put ckPAtStart, bAtStart;
# default units and houselimit
nUnitsI=3;
call PDisplayUnits;
nHouseLimitI=1;
call PDisplayHouseLimit;
call PDisplayPrefStatus;
call BInitBet(false()); # edit prefs only at game start
call DInitMaxBets(nHouseLimit);
# gets rid of double ghost highlighting
hide slPUnits;
hide slPHouseLimit;
show slPUnits;
show slPHouseLimit;
end;
# GENERAL SHOW FORM FUNCTION
function ShowForm(numeric old, numeric new);
if old<>new;
nPriorPriorForm=nPriorForm;
nPriorForm=old;
nForm=new;
if new=0; # main
show frMain;
if nPriorForm=2;
put lbTotal, sfMoney("Total: ",nTotal);
end_if;
# reput labels over redrawn graphics
call RedrawHand;
else;
if new=1; # bet input
if nPriorForm=0;
call BClearBet(bRound2);
end_if;
show frBet;
else;
if new=2; # pref form
# call PDisplayPref
show frPref;
else;
if new=3; # help
put frMsgBox, "Help";
show frMsgBox;
# after show, forces scrollbar show
put lbMMsgText, sMHelp;
else;
if new=4; # about
put frMsgBox, "About";
show frMsgBox;
# after show, forces scrollbar show
put lbMMsgText, sMAbout1+sMAbout2+
sMAbout3+sMAbout4;
else;
end_if;
end_if;
end_if;
end_if;
end_if;
end_if;
end;
# USER (INVOKER) FUNCTIONS
function btDeal;
hide btDeal;
# can't change units or houselimit during hand play
bAllowPrefs=false();
call AnteUp;
call Deal;
end;
function btBet;
hide btBet;
hide btPass;
hide btFold;
# accept any raise
nBet=nBet+nTempBet;
# get bet
hide frMain;
call ShowForm(0,1);
end;
function btPass;
hide btBet;
hide btPass;
hide btFold;
# accept any raise
nBet=nBet+nTempBet;
# clear raise
nTempBet=0;
if bDRaise;
# dealer raise followed by user pass, moves on
if bRound2;
call ReconcileBet;
else;
call UserDrawSelectPrep;
end_if;
else;
# no dealer raise followed by user pass is followed by dealer bet round
if bRound2;
call DDealerBet2;
else;
call DDealerBet1;
end_if;
end_if;
end;
function btFold;
hide btBet;
hide btPass;
hide btFold;
# don't accept any raise
nTempBet=0;
bFold=true();
call ReconcileBet;
end;
function ckHold;
# toggle user draw flag
bHold[invokersub]=not bHold[invokersub];
end;
function btOK;
variables;
numeric i;
numeric n;
end;
# count how many desired discards
i=0;
n=0;
while i<5;
if not bHold[i];
n=n+1;
end_if;
i=i+1;
end_while;
# only proceed if legal
if n<4 or (bfHoldAce(nHand, bHold) and n<5);
i=0;
while i<5;
hide ckHold[i];
i=i+1;
end_while;
hide btOK;
call DealerDrawSelect;
else;
# user confused
put lbDWhat, "Check at least 2 to hold (or 1 Ace)";
end_if;
end;
# INVOKER FUNCTIONS, BET INPUT FORM
function slBDigit0;
call BDisplayBet;
end;
function slBDigit1;
call BDisplayBet;
end;
function btBOK;
hide frBet;
call ShowForm(1,0);
call RedrawHand;
if bRound2;
call DDealerBet2;
else;
call DDealerBet1;
end_if;
end;
function btBReset;
BClearBet(bRound2);
end;
# INVOKER FUNCTIONS, MESSAGE FORM
# swaps main and message box frames, and ok button
# reverses swap
#
function miHelp;
variables;
numeric i;
end;
hide frMain;
if nForm=0 or nForm=4;
call ShowForm(nForm,3);
else;
i=message_box(0,"Help","Can only view from main screen",
"","OK","");
end_if;
end;
function miAbout;
variables;
numeric i;
end;
hide frMain;
if nForm=0 or nForm=3;
call ShowForm(nForm,4);
else;
i=message_box(0,"About","Can only view from main screen",
"","OK","");
end_if;
end;
function btMOK;
hide frMsgBox;
call ShowForm(nForm,0);
end;
# INVOKER FUNCTIONS, PREFERENCES FORM
# swaps main and preferences frame, and ok button
# reverses swap
#
function miPrefs;
variables;
numeric i;
end;
if bAllowPrefs; # and nForm=0;
hide frMain;
ShowForm(nForm,2);
else;
i=message_box(0,"Preferences","Can only change at start of new hand",
"","OK","");
end_if;
end;
function slPUnits;
get slPUnits,nUnitsI;
call PDisplayUnits;
call PDisplayPrefStatus;
call BDisplayBetLabels();
end;
function slPHouseLimit;
get slPHouseLimit,nHouseLimitI;
call PDisplayHouseLimit;
call PDisplayPrefStatus;
call BInitBet(bRound2);
call DInitMaxBets(nHouseLimit);
end;
function btPOK;
get ckPRecommendHold, bRecommendHold;
get ckPAtStart, bAtStart;
hide frMsgBox;
call ShowForm(nForm,0);
end;
function btPReset;
call PDefaultPrefs;
end;
# INVOKE AT START
function Startup;
call ArrangeVisObjects;
call InitVariables;
call PDefaultPrefs; # calls InitBet, InitDealerMaxBets
call Welcome;
# user starts deal when ready
show btDeal;
# allow change of units or houselimit only before hand play
bAllowPrefs=true();
end;